package me.zhengjie.modules.rcon;

import cn.hutool.core.codec.Base64;

import java.io.*;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

public class RconClientDeep {
    private final String host;
    private final int port;
    private final String password;
    private Socket socket;
    private DataInputStream input;
    private DataOutputStream output;
    private int requestId;

    public RconClientDeep(String host, int port, String password) {
        this.host = host;
        this.port = port;
        this.password = password;
        this.requestId = 1; // 初始请求ID
    }

    public void connect() throws IOException {
        // 建立TCP连接
        socket = new Socket(host, port);
        socket.setTcpNoDelay(true);
        input = new DataInputStream(socket.getInputStream());
        output = new DataOutputStream(socket.getOutputStream());

        // 发送认证包
        sendPacket(3, password);

        // 读取认证响应
        Packet authResponse = receivePacket();
        if (authResponse.requestId == -1) {
            throw new IOException("RCON authentication failed: Invalid password");
        }
    }

    public String sendCommand(String command) throws IOException {
        // 发送命令包
        sendPacket(2, command);

        // 读取命令响应
        Packet response = receivePacket();
        return new String(response.payloadData, 0, response.payloadLength - 2); // 移除末尾的2个空字节
    }

    public void disconnect() {
        try {
            if (socket != null) socket.close();
            if (input != null) input.close();
            if (output != null) output.close();
        } catch (IOException e) {
            System.err.println("Error closing connection: " + e.getMessage());
        }
    }

    private void sendPacket(int type, String payload) throws IOException {
        byte[] payloadBytes = payload.getBytes();
        int packetLength = 10 + payloadBytes.length; // 包头10字节 + 有效载荷

        ByteBuffer buffer = ByteBuffer.allocate(packetLength + 4); // 总长度字段(4) + 数据包
        buffer.order(ByteOrder.LITTLE_ENDIAN);

        // 构建数据包
        buffer.putInt(packetLength);    // 长度字段
        buffer.putInt(requestId);        // 请求ID
        buffer.putInt(type);             // 包类型 (3=认证, 2=命令)
        buffer.put(payloadBytes);        // 有效载荷
        buffer.put((byte) 0);            // 载荷终止符1
        buffer.put((byte) 0);            // 载荷终止符2

        // 发送数据包
        output.write(buffer.array());
        output.flush();
    }

    private Packet receivePacket() throws IOException {
        // 读取长度字段 (4字节小端序)
        int length = Integer.reverseBytes(input.readInt()) & 0xFFFF;

        // 读取剩余数据包
        byte[] packetData = new byte[length];
        input.readFully(packetData);

        ByteBuffer buffer = ByteBuffer.wrap(packetData).order(ByteOrder.LITTLE_ENDIAN);

        // 解析数据包
        int requestId = buffer.getInt();
        int type = buffer.getInt();

        // 提取有效载荷 (长度 = 总长度 - 10字节包头)
        byte[] payload = new byte[length - 10];
        buffer.get(payload);

        return new Packet(requestId, type, payload, payload.length);
    }

    private static class Packet {
        final int requestId;
        final int type;
        final byte[] payloadData;
        final int payloadLength;

        Packet(int requestId, int type, byte[] payloadData, int payloadLength) {
            this.requestId = requestId;
            this.type = type;
            this.payloadData = payloadData;
            this.payloadLength = payloadLength;
        }
    }

    public static void main(String[] args) {

        RconClientDeep rcon = new RconClientDeep("59.47.231.71", 25585, "kk507507");
        try {
            rcon.connect();
            System.out.println("Connected to RCON server");

            // 示例命令
            String response = rcon.sendCommand("whitelist_get");
            byte[] decodedBytes = Base64.decode(response);

            System.out.println("Server response: " + new String(decodedBytes));
            System.out.println("Server response: " + response);

        } catch (IOException e) {
            System.err.println("RCON error: " + e.getMessage());
        } finally {
            rcon.disconnect();
        }
    }
}